﻿using System;
using System.IO;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Text;
using DownloadContentKit.Classes;

/*
Developed By: Bhupender Bindra
Developed On: 16th Mar 2011
Description: The code provides the user to download only selected files in zip folder.   
*/
namespace DownloadContentKit.Layouts.DownloadMultipleDocuments
{
    public partial class DownloadZip : LayoutsPageBase
    {
        int checkoutStatus = 0;
        string webTemplate = string.Empty;
        string urlReferrer = string.Empty;

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                //fetch the url by javascript CustomAction.js
                string fullDocLibSourceUrl = Request.Params["sourceUrl"];

                StringBuilder msgScript = new StringBuilder();
                //get the Previous url
                urlReferrer = Request.UrlReferrer.ToString();

                //check the url if empty or not
                if (string.IsNullOrEmpty(fullDocLibSourceUrl)) return;
                string docLibUrl = fullDocLibSourceUrl.Replace(SPContext.Current.Site.Url, "");

                SPList list;
                SPWeb web = SPControl.GetContextWeb(this.Context);
                web.Site.CatchAccessDeniedException = false;

                //Get the webtemplate name
                webTemplate = web.WebTemplate;

                //get the list in this variable
                list = SPContext.Current.Web.GetList(fullDocLibSourceUrl);
                if (!list.IsDocumentLibrary()) return;

                //get all IDs come by javascript CustomAction.js
                string pItemIds = Request.Params["itemIDs"];
                if (string.IsNullOrEmpty(pItemIds)) return;

                SPDocumentLibrary documentLibrary = (SPDocumentLibrary)list;
                //Split all the IDs in array
                string[] sItemIds = pItemIds.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

                int[] itemsIDs = new int[sItemIds.Length];
                int count;
                for (count = 0; count < sItemIds.Length; count++)
                {
                    itemsIDs[count] = Convert.ToInt32(sItemIds[count]);
                }

                //check the length 
                if (itemsIDs.Length > 0)
                {
                    msgScript.Append("<script language='javascript'>");
                    //check the template My site
                    if (webTemplate == "SPSMSITEHOST")
                    {
                        //create a object in memory stream
                        using (MemoryStream memorystream = new MemoryStream())
                        {
                            //create a object to zip file builder and call memory stream
                            using (ZipFileBuilder builder = new ZipFileBuilder(memorystream))
                            {
                                foreach (int id in itemsIDs)
                                {
                                    SPListItem item = documentLibrary.GetItemById(id);
                                    if (item.IsFolder())
                                    {
                                        AddFolder(builder, item.Folder, string.Empty);
                                    }
                                    else
                                    {
                                        AddFile(builder, item.File, string.Empty);
                                    }
                                    //if status is 0 then builder add all the files other wise message display
                                    if (checkoutStatus != 0)
                                    {
                                        msgScript.Append("alert('Please download the files later on. Currently one or more files are checked out by other users.');");
                                        break;
                                    }
                                }
                                if (checkoutStatus == 0)
                                {
                                    builder.Finish();
                                    //call the write function
                                    WriteStreamToResponse(memorystream);
                                }
                            }
                        }
                    }
                    else
                    {
                        //check the current user is admin or not
                        if (web.CurrentUser.IsSiteAdmin)
                        {
                            //create a object in memory stream
                            using (MemoryStream memorystream = new MemoryStream())
                            {
                                //create a object to zip file builder and call memory stream
                                using (ZipFileBuilder builder = new ZipFileBuilder(memorystream))
                                {
                                    foreach (int id in itemsIDs)
                                    {
                                        SPListItem item = documentLibrary.GetItemById(id);
                                        if (item.IsFolder())
                                        {
                                            AddFolder(builder, item.Folder, string.Empty);
                                        }
                                        else
                                        {
                                            AddFile(builder, item.File, string.Empty);
                                        }
                                        //if status is 0 then builder add all the files other wise message display
                                        if (checkoutStatus != 0)
                                        {
                                            msgScript.Append("alert('Please download the files later on. Currently one or more files are checked out by other users.');");
                                            break;
                                        }
                                    }
                                    if (checkoutStatus == 0)
                                    {
                                        builder.Finish();
                                        //call the write function
                                        WriteStreamToResponse(memorystream);
                                    }
                                }
                            }
                        }
                        else
                        {
                            msgScript.Append("alert('You do not have sufficient priviledges to download the documents.');");
                        }
                    }
                    msgScript.Append("window.location.replace('" + urlReferrer.ToString() + "');");
                    msgScript.Append("</script>");
                    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "MyScript", msgScript.ToString());
                }
            }
            catch (Exception ex)
            {
                string errMessage = ex.Message;
                errMessage = errMessage.Replace("'", "");
                StringBuilder errScript = new StringBuilder();
                errScript.Append("<script language='javascript'>");
                errScript.Append("alert('" + errMessage.ToString() + "');");
                errScript.Append("window.location.replace('" + urlReferrer.ToString() + "');");
                errScript.Append("</script>");
                Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "MyScript", errScript.ToString());
            }

        }


        /// <summary>
        /// this function used to add file in zip builder and check status
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="file"></param>
        /// <param name="folder"></param>
        public void AddFile(ZipFileBuilder builder, SPFile file, string folder)
        {
            if (file.CheckOutStatus != SPFile.SPCheckOutStatus.None)
            {
                checkoutStatus = 1;
            }
            else
            {
                using (Stream fileStream = file.OpenBinaryStream())
                {
                    builder.Add(folder + "\\" + file.Name, fileStream);
                    fileStream.Close();
                }
            }
        }

        /// <summary>
        /// this function used to add folder and then file in zip builder
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="folder"></param>
        /// <param name="parentFolder"></param>
        private void AddFolder(ZipFileBuilder builder, SPFolder folder, string parentFolder)
        {
            string folderPath = parentFolder == string.Empty ? folder.Name : parentFolder + "\\" + folder.Name;
            builder.AddDirectory(folderPath);

            foreach (SPFile file in folder.Files)
            {
                AddFile(builder, file, folderPath);
            }

            foreach (SPFolder subFolder in folder.SubFolders)
            {
                AddFolder(builder, subFolder, folderPath);
            }
        }

        /// <summary>
        /// this function used to write the files in zip folder
        /// </summary>
        /// <param name="ms"></param>
        private void WriteStreamToResponse(MemoryStream ms)
        {
            if (ms.Length > 0)
            {
                string fileName = DateTime.Now.ToFileTime().ToString() + ".zip";
                Response.Clear();
                Response.ClearHeaders();
                Response.ClearContent();
                Response.AddHeader("Content-Length", ms.Length.ToString());
                Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
                Response.ContentType = "application/octet-stream";

                byte[] buffer = new byte[ms.Length];
                ms.Position = 0;
                int num;
                do
                {
                    num = ms.Read(buffer, 0, buffer.Length);
                    Response.OutputStream.Write(buffer, 0, num);
                }

                while (num > 0);
                Response.Flush();
                Response.Clear();
            }
        }
    }
}
